﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace SquaredEngine.Utils.Path.Curves {
	public class CurveNodesContainer : ICurveNodesContainer {
		private List<Vector3> controlNodes;
		/// <summary>
		/// Gets or sets a list of control nodes
		/// </summary>
		public List<Vector3> ControlNodes {
			get { return this.controlNodes; }
			set {
				if (value != null)
					this.controlNodes = value;
			}
		}

		private List<Vector3> curveNodes;
		/// <summary>
		/// Gets a list of curve nodes
		/// </summary>
		public List<Vector3> CurveNodes {
			get { return this.curveNodes; }
		}



		public CurveNodesContainer() {
			this.controlNodes = new List<Vector3>();
			this.curveNodes = new List<Vector3>();
		}


		/// <summary>
		/// Adds given control node to end of list
		/// </summary>
		/// <param name="node">Control node to add</param>
		public virtual void AddLast(Vector3 node) {
			this.controlNodes.Add(node);
		}

		/// <summary>
		/// Adds given control node to beginning of list
		/// </summary>
		/// <param name="node">Control node to add</param>
		public virtual void AddFirst(Vector3 node) {
			this.controlNodes.Insert(0, node);
		}

		/// <summary>
		/// Adds given control node to specified position
		/// </summary>
		/// <param name="index">Zero based index representing position</param>
		/// <param name="node">Control node to add</param>
		/// <returns>False when index isn't valid</returns>
		public virtual Boolean AddAfter(Int32 index, Vector3 node) {
			if (index >= this.controlNodes.Count) return false;

			this.controlNodes.Insert(index, node);
			return true;
		}

		/// <summary>
		/// Adds given control node after specified node
		/// </summary>
		/// <param name="searchNode">After which node to add new control node</param>
		/// <param name="node">Control node to add</param>
		/// <returns>False when searchNode doesn't exists</returns>
		public virtual Boolean AddAfter(Vector3 searchNode, Vector3 node) {
			if (!this.controlNodes.Contains(searchNode)) return false;

			return AddAfter(this.controlNodes.IndexOf(searchNode), node);
		}

		/// <summary>
		/// Adds given control nodes after specified index
		/// </summary>
		/// <param name="index">Zero based index representing position</param>
		/// <param name="nodes">Control nodes to add</param>
		/// <returns>False when index isn't valid</returns>
		public virtual Boolean AddRangeAfter(Int32 index, Vector3[] nodes) {
			if (nodes == null) return false;
			if (index >= this.controlNodes.Count) return false;

			int insertCounter = index;
			foreach (Vector3 nodeToInsert in nodes) {
				this.controlNodes.Insert(insertCounter++, nodeToInsert);
			}

			return true;
		}

		/// <summary>
		/// Removes given node from list
		/// </summary>
		/// <param name="node">Control node to remove</param>
		/// <returns>True when node successfully removed</returns>
		public virtual Boolean Remove(Vector3 node) {
			return this.controlNodes.Remove(node);
		}

		/// <summary>
		/// Removes node at given index
		/// </summary>
		/// <param name="index">Zero based index representing position of control node to remove</param>
		/// <returns>True when index is valid and node is successfully removed</returns>
		public virtual Boolean Remove(Int32 index) {
			if (index >= this.controlNodes.Count) return false;

			this.controlNodes.RemoveAt(index);

			return true;
		}

		/// <summary>
		/// Clears both control and curve nodes
		/// </summary>
		public virtual void Clear() {
			this.controlNodes.Clear();
			this.curveNodes.Clear();
		}


		/// <summary>
		/// Fills CurveNodes with nodes generated by generator
		/// </summary>
		/// <param name="generator">Generator that generated curve nodes</param>
		/// <returns>Generated list corresponds to CurvesNode property</returns>
		public virtual List<Vector3> GetCurveNodesFrom(ICurveGenerator generator) {
			this.curveNodes = generator.Generate(this.controlNodes);

			return CurveNodes;
		}
	}
}
